package com.zzyl.nursing.service.impl;

import cn.hutool.http.HttpUtil;
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
import com.zzyl.common.exception.base.BaseException;
import com.zzyl.common.utils.StringUtils;
import com.zzyl.nursing.service.WechatService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.util.HashMap;
import java.util.Map;

/**
 * 实现类
 *
 * @Author mr.lcc
 * @Data 2025/5/23 16:38
 */
@Slf4j
@Service
public class WechatServiceImpl implements WechatService {

    /**
     * 小程序appId
     */
    @Value("${wechat.appId}")
    private String appId;

    /**
     * 小程序appSecret
     */
    @Value("${wechat.appSecret}")
    private String appSecret;

    /**
     * 小程序登录：获取openId的请求地址
     */
    private static final String GET_OPEN_ID_URL = "https://api.weixin.qq.com/sns/jscode2session";

    /**
     * 小程序获取用户手机号前准备：获取接口调用凭证的请求地址
     */
    private static final String GET_ACCESS_TOKEN_URL = "https://api.weixin.qq.com/cgi-bin/token";

    /**
     * 获取手机号的请求地址
     */
    private static final String POST_GET_PHONE_NUM_URL = "https://api.weixin.qq.com/wxa/business/getuserphonenumber?access_token=";


    /**
     * 根据临时凭证码（openId获取专用凭证码）获取openId
     *
     * @param code
     * @return
     */
    @Override
    public String getOpenId(String code) {

        log.info("1.准备请求参数");
        // 1.1 获取基础请求参数的准备
        Map<String, Object> queryParams = getBaseParams();
        // 1.2 必要请求参数，code是前端请求wx.login获取的参数，grant_type是固定的参数。
        queryParams.put("js_code", code);
        queryParams.put("grant_type", "authorization_code");

        log.info("2.使用hutool工具类发起GET请求调用小程序接口");
        // 2.1 发起GET请求到微信服务器，获取响应结果。
        String resultJSON = HttpUtil.get(GET_OPEN_ID_URL, queryParams);
        // 2.2 判断响应结果是否为空
        if (StringUtils.isBlank(resultJSON)) {
            throw new BaseException("获取openId失败");
        }

        log.info("3.解析相应结果中的openId");
        // 3.1 将响应结果为JSON格式后获取的JSON对象
        JSONObject jsonObject = JSON.parseObject(resultJSON);

        // 3.2 判断响应结果是否成功
        Integer errcode = jsonObject.getInteger("errcode");
        if (errcode != null && errcode != 0) {
            throw new BaseException("调用微信小程序登录接口失败");
        }

        log.info("4.返回openId");
        return jsonObject.getString("openid");
    }

    /**
     * 根据临时凭证码（手机号获取专用凭证码，非openId凭证码）获取手机号
     *
     * @param code
     * @return
     */
    @Override
    public String getPhone(String code) {
        // 1. 准备请求参数
        Map<String, Object> paramMap = new HashMap<>();
        paramMap.put("code", code);

        // 2. 获取接口调用凭证，获取请求参数access_token，直接拼贴在接口地址后面，拼接上&access_token=。
        String accessToken = this.getAccessToken();

        // 2. 使用hutool工具发起POST请求微信获取手机号接口
        String resultJSON = HttpUtil.post(POST_GET_PHONE_NUM_URL + accessToken, JSON.toJSONString(paramMap));
        // 2.1 判断响应结果是否为空
        if (StringUtils.isBlank(resultJSON)) {
            throw new BaseException("调用微信获取手机号接口失败");
        }

        // 3. 得到响应结果，得到phoneNumber手机号
        JSONObject jsonObject = JSON.parseObject(resultJSON);
        // 3.1 判断响应结果是否成功
        Integer errcode = jsonObject.getInteger("errcode");
        if (errcode != null && errcode != 0) {
            throw new BaseException("调用微信获取手机号接口失败");
        }

        // 4.处理响应结果，得到手机号。
        // 4.1 获取一级参数：phone_info
        String phoneInfo = jsonObject.getString("phone_info");
        // 4.2 解析一级参数，得到二级参数：phoneNumber
        JSONObject phoneInfoObject = JSON.parseObject(phoneInfo);

        // 5.返回手机号
        return phoneInfoObject.getString("phoneNumber");
    }

    /**
     * 获取接口调用凭证为获取手机号准备参数
     *
     * @return
     */
    private String getAccessToken() {
        // 1. 准备请求参数
        Map<String, Object> paramMap = getBaseParams();
        // 1.1 处理两个基础参数外，还需要准备第三个参数grant_type
        paramMap.put("grant_type", "client_credential");

        // 2. 使用hutool工具发起GET请求微信获取接口调用凭据接口
        String resultJSON = HttpUtil.get(GET_ACCESS_TOKEN_URL, paramMap);

        // 2.1 判断响应结果是否为空
        if (StringUtils.isBlank(resultJSON)) {
            throw new BaseException("调用获取接口凭证的接口失败");
        }

        // 3. 解析响应结果，得到access_token接口访问凭证
        JSONObject jsonObject = JSON.parseObject(resultJSON);
        // 3.1 判断响应结果是否成功
        Integer errcode = jsonObject.getInteger("errcode");
        if (errcode != null && errcode != 0) {
            throw new BaseException("调用获取接口凭证的接口失败");
        }

        // 4.返回access_token
        return jsonObject.getString("access_token");
    }

    /**
     * 获取基础请求参数
     *
     * @return
     */
    private Map<String, Object> getBaseParams() {
        // 基础请求参数的准备
        Map<String, Object> params = new HashMap<>();
        params.put("appid", appId);
        params.put("secret", appSecret);
        return params;
    }
}
